package vista;

import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;

import javax.swing.DefaultListModel;
import javax.swing.ListSelectionModel;

import mapas.Region;
import unidades.Unidad;
import clasesGenerales.Conjunto;
import control.ataque.BotonAtacarListener;
import control.juego.ControladorSeleccion;
import control.ronda.controladorFinTurno;
import edificios.Edificio;

/**
 * @author Grupo 2, Algoritmos y programacion 3, Catedra Fontela<br>1er cuat 2007    
 * <br> Esta clase se encarga de representar la vista para realizar los ataques.
 */

public class VistaAtaque extends VentanaConDosListas implements Observer,CerrablePorFinTurno{

	//Modelo
	private Region regionAtacante;
	private Region regionAtacada;
	
	private static String subtitulo1 = "Atacantes";
	private static String subtitulo2 = "Atacados";
	private static String accion = "Atacar";
	
	private static VistaAtaque Instance = null;
	
	/**
	 * Se encarga de inicializar la vista de ataques
	 * @param titulo Titulo de la ventana
	 */
	private VistaAtaque(String titulo){
		//Llamo al constructor del padre
		super(titulo, subtitulo1, subtitulo2, accion);
		//agrego la funcionalidad a los botones
		this.ActivarComportamientoBotonAccion();
		this.ActivarComportamientoBotonSalir();
		//pongo la referencia a la instancia
		Instance = this;
		//lo inscribo como vista cerrable en fin de turno
		controladorFinTurno.getInstance().agregarVistaCerrable(this);
	}
	
	/**
	 * Coloca las nuevas regiones atacante y defensora
	 */
	public void actualizarModelo(){
		String titulo = " - BATALLA  ENTRE ";
		if (regionAtacada != null){
			regionAtacada.deleteObserver(this);
			borrarObservadoresUnidades(regionAtacada);
			borrarObservadoresEdificios(regionAtacada);
		}
		if (regionAtacante != null){
			regionAtacante.deleteObserver(this);
			borrarObservadoresUnidadesAtacantes(regionAtacante);
		}
		//Conecto con el modelo
		this.regionAtacante = ControladorSeleccion.GetInstance().getSlot1();
		this.regionAtacada = ControladorSeleccion.GetInstance().getSlot2();
		if (regionAtacante!=null){
			regionAtacante.addObserver(this);
			titulo += regionAtacante.getNombre();
		} else
			titulo += "NINGUNA";
		titulo += " Y ";
		if (regionAtacada!=null){
			regionAtacada.addObserver(this);
			titulo += regionAtacada.getNombre();
		} else
			titulo += "NINGUNA";
		titulo += " - ";
		this.setTitle(titulo);
		this.update(null,null);
	}

	/**
	 * @return La unica instancia de la VistaAtaque
	 */
	public static VistaAtaque getInstance(){
		if (Instance == null)
			new VistaAtaque(" - BATALLA - ");
		Instance.actualizarModelo();
		return Instance;
	}
	
	/**
	 * Establece los modos de seleccion de las listas.
	 */
	protected void establecerModosDeSeleccion(){
		getLista1().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		getLista2().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
	}
	
	/**
	 * Se encarga de actualizar la vista, cuando el modelo cambie
	 */
	public void update(Observable arg0, Object arg1) {
		//Remuevo todos los elementos de las listas
		this.getModelo1().removeAllElements();
		this.getModelo2().removeAllElements();
		//Les cargo todo nuevamente
		if (regionAtacante != null)
			CargarUnidadesAtacantes(this.getModelo1(), regionAtacante);
		if (regionAtacada != null){
			CargarUnidades(this.getModelo2(), regionAtacada);
			CargarEdificios(this.getModelo2(), regionAtacada);
		}
	}

	/**
	 * Carga los edificios de una region en un modelo de lista
	 * @param modeloLista Modelo donde cargar los edificios
	 * @param region Region que contiene a los edificios
	 */
	private void CargarEdificios(DefaultListModel modeloLista, Region region){
		//Obtengo los edificios
		Conjunto edificios = region.getEdificios();
		//Monto un iterador y recorro los elementos
		Iterator iterador = edificios.iterator();
		while (iterador.hasNext()){
			//Obtengo cada edificio y lo agrego al modelo de la lista
			Edificio edificio = (Edificio) iterador.next();
			modeloLista.addElement(edificio);
			edificio.addObserver(this);
		}
	}
	
	/**
	 * Carga las unidades de una region en un modelo de lista
	 * @param modeloLista Modelo donde cargar las unidades
	 * @param region Region que contiene a las unidades
	 */
	private void CargarUnidades(DefaultListModel modeloLista, Region region){
		//Obtengo las unidades
		Conjunto unidades = region.getUnidades();
		//Monto un iterador y recorro los elementos
		Iterator iterador = unidades.iterator();
		while (iterador.hasNext()){
			//Obtengo cada unidad y la agrego al modelo de la lista
			Unidad unidad = (Unidad) iterador.next();
			modeloLista.addElement(unidad);
			unidad.addObserver(this);
		}
	}

	/**
	 * Carga las unidades que pueden atacar en una region en un modelo de lista
	 * @param modeloLista Modelo donde cargar las unidades
	 * @param region Region que contiene a las unidades
	 */
	private void CargarUnidadesAtacantes(DefaultListModel modeloLista, Region region){
		//Obtengo las unidades
		Conjunto unidades = region.getUnidades();
		//Monto un iterador y recorro los elementos
		Iterator iterador = unidades.iterator();
		while (iterador.hasNext()){
			//Obtengo cada unidad y la agrego al modelo de la lista
			Unidad unidad = (Unidad) iterador.next();
			if ((unidad.getAtaque() > 0) && (unidad.getDespRestante() > 0)){
				modeloLista.addElement(unidad);
				unidad.addObserver(this);
			}
		}
	}
	
	/**
	 * Saca esta vista como observadora de las unidades de una region
	 * @param region Region a remover observadores
	 */
	private void borrarObservadoresUnidades(Region region){
		//Obtengo las unidades
		Conjunto unidades = region.getUnidades();
		//Monto un iterador y recorro los elementos
		Iterator iterador = unidades.iterator();
		while (iterador.hasNext()){
			//Obtengo cada unidad y le saco esta vista como observadora
			Unidad unidad = (Unidad) iterador.next();
			unidad.deleteObserver(this);
		}
	}
	
	/**
	 * Saca esta vista como observadora de los edificios de una region
	 * @param region Region a remover observadores
	 */
	private void borrarObservadoresEdificios(Region region){
		//Obtengo los edificios
		Conjunto edificios = region.getEdificios();
		//Monto un iterador y recorro los elementos
		Iterator iterador = edificios.iterator();
		while (iterador.hasNext()){
			//Obtengo cada edificio y le saco esta vista como observadora
			Edificio edificio = (Edificio) iterador.next();
			edificio.deleteObserver(this);
		}
	}
	
	/**
	 * Saca esta vista como observadora de las unidades atacantes de una region
	 * @param region Region a remover observadores
	 */
	private void borrarObservadoresUnidadesAtacantes(Region region){
		//Obtengo las unidades
		Conjunto unidades = region.getUnidades();
		//Monto un iterador y recorro los elementos
		Iterator iterador = unidades.iterator();
		while (iterador.hasNext()){
			//Obtengo cada unidad y le saco esta vista como observadora
			Unidad unidad = (Unidad) iterador.next();
			if ((unidad.getAtaque() > 0) && (unidad.getDespRestante() > 0)){
				unidad.deleteObserver(this);
			}
		}
	}
	/**
	 * @return La region atacante
	 */
	public Region getRegionAtacante(){
		return this.regionAtacante;
	}
	
	/**
	 * @return La region atacada
	 */
	public Region getRegionAtacada(){
		return this.regionAtacada;
	}
	
	/**
	 * Activa el comportamiento del boton accion.
	 * Le asigna la accion de atacar.
	 */
	protected void ActivarComportamientoBotonAccion(){
		this.getBotonAccion().addActionListener(new BotonAtacarListener(this));
	}

	public void CerrarVentana() {
		this.setVisible(false);
	}
}
